
namespace gen {

	template <typename S, typename CondT>
    template <typename InfoT>
	void
	if_generator<S,CondT>::generate(InfoT & info) const
	{
		typedef typename InfoT::iterator_t		iterator_t;
		typedef typename InfoT::multi_domain_t	multi_domain_t;
		typedef typename InfoT::sub_domains_t	sub_domains_t;
		typedef typename InfoT::sub_domains_iterator_t
                                        		sub_domains_iterator_t;
		typedef domain<iterator_t>				domain_t;

		domain_t * result;
		// get sub domain
		unsigned long pid = this->m_pid;
		multi_domain_t & multi_domain = info.domain();
		sub_domains_t & sub_domains = multi_domain.sub_domains();
		sub_domains_iterator_t i = sub_domains.find(pid);
		if (i == sub_domains.end()){
			// evaluate		
			result = new domain_t(
							this->right().evaluate(info));
			sub_domains.insert(pid, result);
		}
		else result = static_cast<domain_t*>(i->second);

		// generate
		if ( result->point(info.current()) )
		{
			// update limit [first, last], not entire domain
			result->shrinkPositiveBounds(multi_domain.firstPositive(), multi_domain.lastPositive());
			domain_t instanceDomain = multi_domain.swapDomain(*result);
			this->left().generate(info);
			multi_domain.swapDomain(instanceDomain);
		}		
	}

    template <typename DerivedT>
	template <class T>
	inline if_generator< DerivedT, T >
	generator<DerivedT>::operator[](cond_expr<T> const& c) const
    {
        return if_generator< DerivedT, T >(derived(), c.derived());
    }

    template <typename DerivedT>
	inline if_generator< DerivedT, cst_expr >
	generator<DerivedT>::operator[](bool b) const
    {
        return if_generator< DerivedT, cst_expr >(derived(), cst_expr(b));
    }

};
